home *** CD-ROM | disk | FTP | other *** search
- /* TrackRebuild.c */
- /*
- * Copyright © 1989 Martin Minow. All rights reserved.
- *
- * This routine is called whenever the contents of
- * the TrackRecord text changes. It rebuilds the
- * line start vector and repaints the display.
- */
- #include "TrackEdit.h"
- #define TR (*tr)
- #define NIL 0L
- #define TR_SIZE(tr) \
- sizeof (TrackRecord) + (sizeof (DOT) * (*tr).nLines);
-
- static TrackPtr newline(TrackHandle, DOT);
-
- /*
- * _Track_rebuild(track_handle, start)
- *
- * _Track_rebuild() is called whenever the content of
- * the TrackRecord text string changes. It rebuilds
- * the lineStarts vector and forces the text to be
- * redrawn on the screen. _Track_rebuild is the only
- * routine that understands line breaks and such.
- * Walk through the string to build a vector that locates
- * the start of each line. There is always one extra entry
- * so the number of characters in the last line can be
- * computed. The display window is the current port.
- * Note that the word/line algorithm only notices
- * whitespace. The start parameter identifies the first
- * character that has changed.
- *
- * Since _Track_rebuild temporarily unlocks the
- * TrackRecord, it returns the current value of the
- * relocked record.
- */
- TrackPtr
- _Track_rebuild(track_handle, start)
- TrackHandle track_handle;
- DOT start;
- {
- register TrackPtr tr;
- register unsigned c;
- register DOT index;
- register DOT line_break; /* space here */
- register DOT line_start; /* -> start of line */
- register INTEGER line_width; /* Current width */
- LONGINT size;
- LONGINT row;
- LONGINT old_row, new_row;
- Rect box;
-
- tr = *track_handle;
- MoveHHi(TR.hText); /* Lock the text */
- HLock(TR.hText); /* record. */
- if (start == 0) {
- TR.nLines = 0;
- index = 0;
- }
- else {
- /*
- * Start at the previous line since, if we delete
- * the end of the first word on a line, it might
- * fit on the previous line.
- */
- TR.nLines = _Track_row(tr, start);
- if (TR.nLines > 0)
- --TR.nLines;
- index = TR.lineStarts[TR.nLines];
- }
- /*
- * Get the screen position *before* munging the lines.
- */
- old_row = _Track_row(tr, start);
- tr = newline(track_handle, index);
- line_start = index;
- line_width = 0;
- line_break = 0;
- /*
- * Each pass through this loop eats one character.
- */
- while (index < TR.textLength) {
- c = (*TR.hText)[index++]; /* Grab the byte */
- if (c == '\r')
- goto do_newline;
- line_width += CharWidth(c);
- if (TR.crOnly < 0 || line_width <= TR.lineWidth) {
- /*
- * This byte fits. If it's a word break, remember
- * its location for the end of line test.
- */
- if (_Track_is_white(tr, *TR.hText, index - 1))
- line_break = index;
- }
- else {
- /*
- * We're at the end of the line. If we've seen
- * a word, break the line there. Else, break
- * at the previous byte (if there is one on this
- * line, if the first byte on the line doesn't
- * fit, stuff it in so we don't loop forever.
- */
- if (line_break != 0)
- index = line_break; /* Break at word */
- else if (index > (line_start + 1)) {
- --index; /* Rescan this one */
- }
- do_newline:
- tr = newline(track_handle, index);
- line_start = index;
- line_width = 0;
- line_break = 0;
- }
- } /* Loop on characters */
- TR.lineStarts[TR.nLines] = TR.textLength;
- HUnlock(TR.hText);
- /*
- * All of the line lengths have been set. Adjust
- * the TrackRecord size in case it's shrunk.
- */
- size = TR_SIZE(tr)
- if (size > GetHandleSize(track_handle)) {
- HUnlock(track_handle);
- SetHandleSize(track_handle, size);
- MoveHHi(track_handle);
- HLock(track_handle);
- tr = *track_handle;
- }
- /*
- * Locate this row on the screen. If it (or anything
- * later on) will be visible, repaint as little
- * as possible. Note that we may have to repaint
- * the row that the selection *was* on before we
- * started messing with the lines.
- */
- new_row = _Track_row(tr, start);
- if (new_row < old_row)
- old_row = new_row;
- row = _Track_row_pixel(tr, old_row) - TR.fontAscent;
- box = TR.viewRect;
- if (row <= (LONGINT) box.bottom) {
- if (row > (LONGINT) box.top)
- box.top = row;
- EraseRect(&box);
- _Track_do_update(tr, &box);
- ValidRect(&box);
- }
- return (tr);
- }
-
-
- /*
- * newline()
- * Called when a new line is ready: this sets the
- * handle size and stores the index to the first
- * character in this line.
- */
- static TrackPtr
- newline(track_handle, index)
- TrackHandle track_handle;
- DOT index;
- {
- register TrackPtr tr;
- _Track_state state;
- LONGINT size;
-
- tr = *track_handle;
- ++TR.nLines;
- size = TR_SIZE(tr);
- if (size > GetHandleSize(track_handle)) {
- /*
- * Reallocate the track handle to its proper size.
- * You can allocate a chunk of lines here without
- * problems.
- */
- HUnlock(track_handle);
- SetHandleSize(track_handle, size);
- MoveHHi(track_handle);
- HLock(track_handle);
- tr = *track_handle;
- }
- TR.lineStarts[TR.nLines - 1] = index;
- return (tr);
- }
-
-